use crate::public::{
  KeybdKey::{self, *},
  MouseButton::{self, *},
};

impl From<KeybdKey> for u64 {
  // https://www.cl.cam.ac.uk/~mgk25/ucs/keysymdef.h
  // https://github.com/AltF02/x11-rs/blob/master/src/keysym.rs
  fn from(key: KeybdKey) -> u64 {
    match key {
      BackspaceKey => 0xff08,
      TabKey => 0xff09,
      EnterKey => 0xff8d,
      EscapeKey => 0xff1b,
      SpaceKey => 0x020,
      PageUpKey => 0xff55,
      PageDownKey => 0xff56,
      EndKey => 0xff56,
      HomeKey => 0xff50,
      LeftKey => 0xff51,
      UpKey => 0xff52,
      RightKey => 0xff53,
      DownKey => 0xff54,
      InsertKey => 0xff63,
      DeleteKey => 0xff9f,
      Numrow0Key => 0x030,
      Numrow1Key => 0x031,
      Numrow2Key => 0x032,
      Numrow3Key => 0x033,
      Numrow4Key => 0x034,
      Numrow5Key => 0x035,
      Numrow6Key => 0x036,
      Numrow7Key => 0x037,
      Numrow8Key => 0x038,
      Numrow9Key => 0x039,
      AKey => 0x041,
      BKey => 0x042,
      CKey => 0x043,
      DKey => 0x044,
      EKey => 0x045,
      FKey => 0x046,
      GKey => 0x047,
      HKey => 0x048,
      IKey => 0x049,
      JKey => 0x04a,
      KKey => 0x04b,
      LKey => 0x04c,
      MKey => 0x04d,
      NKey => 0x04e,
      OKey => 0x04f,
      PKey => 0x050,
      QKey => 0x051,
      RKey => 0x052,
      SKey => 0x053,
      TKey => 0x054,
      UKey => 0x055,
      VKey => 0x056,
      WKey => 0x057,
      XKey => 0x058,
      YKey => 0x059,
      ZKey => 0x05a,
      LSuper => 0xffeb,
      RSuper => 0xffec,
      Numpad0Key => 0xffb0,
      Numpad1Key => 0xffb1,
      Numpad2Key => 0xffb2,
      Numpad3Key => 0xffb3,
      Numpad4Key => 0xffb4,
      Numpad5Key => 0xffb5,
      Numpad6Key => 0xffb6,
      Numpad7Key => 0xffb7,
      Numpad8Key => 0xffb8,
      Numpad9Key => 0xffb9,
      F1Key => 0xffbe,
      F2Key => 0xffbf,
      F3Key => 0xffc0,
      F4Key => 0xffc1,
      F5Key => 0xffc2,
      F6Key => 0xffc3,
      F7Key => 0xffc4,
      F8Key => 0xffc5,
      F9Key => 0xffc6,
      F10Key => 0xffc7,
      F11Key => 0xffc8,
      F12Key => 0xffc9,
      F13Key => 0xffca,
      F14Key => 0xffcb,
      F15Key => 0xffcc,
      F16Key => 0xffcd,
      F17Key => 0xffce,
      F18Key => 0xffcf,
      F19Key => 0xffd0,
      F20Key => 0xffd1,
      F21Key => 0xffd2,
      F22Key => 0xffd3,
      F23Key => 0xffd4,
      F24Key => 0xffd5,
      NumLockKey => 0xff7f,
      ScrollLockKey => 0xff14,
      CapsLockKey => 0xffe5,
      LShiftKey => 0xffe1,
      RShiftKey => 0xffe2,
      LControlKey => 0xffe3,
      RControlKey => 0xffe4,
      LAltKey => 0xffe9,
      RAltKey => 0xffea,
      CommandKey => 0xffeb,
      BrowserBackKey => 0x1008ff26,
      BrowserForwardKey => 0x1008ff27,
      BrowserRefreshKey => 0x1008ff29,
      VolumeMuteKey => 0x1008ff12,
      VolumeDownKey => 0x1008ff11,
      VolumeUpKey => 0x1008ff13,
      MediaNextTrackKey => 0x1008ff17,
      MediaPrevTrackKey => 0x1008ff16,
      MediaStopKey => 0x1008ff15,
      MediaPlayPauseKey => 0x1008ff14,
      BackquoteKey => 0x29,
      SlashKey => 0x35,
      BackslashKey => 0x2b,
      CommaKey => 0x33,
      PeriodKey => 0x34,
      MinusKey => 0x0c,
      QuoteKey => 0x28,
      SemicolonKey => 0x27,
      LBracketKey => 0x1a,
      RBracketKey => 0x1b,
      EqualKey => 0x0d,
      OtherKey(keycode) => keycode,
    }
  }
}

impl From<u64> for KeybdKey {
  // https://www.cl.cam.ac.uk/~mgk25/ucs/keysymdef.h
  // https://github.com/AltF02/x11-rs/blob/master/src/keysym.rs
  fn from(code: u64) -> KeybdKey {
    match code {
      0xff08 => BackspaceKey,
      0xff09 => TabKey,
      0xff8d => EnterKey,
      0xff1b => EscapeKey,
      0x020 => SpaceKey,
      0xff55 => PageUpKey,
      0xff56 => PageDownKey,
      0xff56 => EndKey,
      0xff50 => HomeKey,
      0xff51 => LeftKey,
      0xff52 => UpKey,
      0xff53 => RightKey,
      0xff54 => DownKey,
      0xff63 => InsertKey,
      0xff9f => DeleteKey,
      0x030 => Numrow0Key,
      0x031 => Numrow1Key,
      0x032 => Numrow2Key,
      0x033 => Numrow3Key,
      0x034 => Numrow4Key,
      0x035 => Numrow5Key,
      0x036 => Numrow6Key,
      0x037 => Numrow7Key,
      0x038 => Numrow8Key,
      0x039 => Numrow9Key,
      0x041 => AKey,
      0x042 => BKey,
      0x043 => CKey,
      0x044 => DKey,
      0x045 => EKey,
      0x046 => FKey,
      0x047 => GKey,
      0x048 => HKey,
      0x049 => IKey,
      0x04a => JKey,
      0x04b => KKey,
      0x04c => LKey,
      0x04d => MKey,
      0x04e => NKey,
      0x04f => OKey,
      0x050 => PKey,
      0x051 => QKey,
      0x052 => RKey,
      0x053 => SKey,
      0x054 => TKey,
      0x055 => UKey,
      0x056 => VKey,
      0x057 => WKey,
      0x058 => XKey,
      0x059 => YKey,
      0x05a => ZKey,
      0xffeb => LSuper,
      0xffec => RSuper,
      0xffb0 => Numpad0Key,
      0xffb1 => Numpad1Key,
      0xffb2 => Numpad2Key,
      0xffb3 => Numpad3Key,
      0xffb4 => Numpad4Key,
      0xffb5 => Numpad5Key,
      0xffb6 => Numpad6Key,
      0xffb7 => Numpad7Key,
      0xffb8 => Numpad8Key,
      0xffb9 => Numpad9Key,
      0xffbe => F1Key,
      0xffbf => F2Key,
      0xffc0 => F3Key,
      0xffc1 => F4Key,
      0xffc2 => F5Key,
      0xffc3 => F6Key,
      0xffc4 => F7Key,
      0xffc5 => F8Key,
      0xffc6 => F9Key,
      0xffc7 => F10Key,
      0xffc8 => F11Key,
      0xffc9 => F12Key,
      0xffca => F13Key,
      0xffcb => F14Key,
      0xffcc => F15Key,
      0xffcd => F16Key,
      0xffce => F17Key,
      0xffcf => F18Key,
      0xffd0 => F19Key,
      0xffd1 => F20Key,
      0xffd2 => F21Key,
      0xffd3 => F22Key,
      0xffd4 => F23Key,
      0xffd5 => F24Key,
      0xff7f => NumLockKey,
      0xff14 => ScrollLockKey,
      0xffe5 => CapsLockKey,
      0xffe1 => LShiftKey,
      0xffe2 => RShiftKey,
      0xffe3 => LControlKey,
      0xffe4 => RControlKey,
      0xffe9 => LAltKey,
      0xffea => RAltKey,
      0x1008ff26 => BrowserBackKey,
      0x1008ff27 => BrowserForwardKey,
      0x1008ff29 => BrowserRefreshKey,
      0x1008ff12 => VolumeMuteKey,
      0x1008ff11 => VolumeDownKey,
      0x1008ff13 => VolumeUpKey,
      0x1008ff17 => MediaNextTrackKey,
      0x1008ff16 => MediaPrevTrackKey,
      0x1008ff15 => MediaStopKey,
      0x1008ff14 => MediaPlayPauseKey,
      0x29 => BackquoteKey,
      0x35 => SlashKey,
      0x2b => BackslashKey,
      0x33 => CommaKey,
      0x34 => PeriodKey,
      0x0c => MinusKey,
      0x28 => QuoteKey,
      0x27 => SemicolonKey,
      0x1a => LBracketKey,
      0x1b => RBracketKey,
      0x0d => EqualKey,
      _ => OtherKey(code),
    }
  }
}

impl From<u32> for MouseButton {
  fn from(keycode: u32) -> MouseButton {
    match keycode {
      1 => LeftButton,
      2 => MiddleButton,
      3 => RightButton,
      4 => X1Button,
      5 => X2Button,
      _ => OtherButton(keycode),
    }
  }
}

impl From<MouseButton> for u32 {
  fn from(button: MouseButton) -> u32 {
    match button {
      LeftButton => 1,
      MiddleButton => 2,
      RightButton => 3,
      X1Button => 4,
      X2Button => 5,
      OtherButton(keycode) => keycode,
    }
  }
}

// https://www.win.tue.nl/~aeb/linux/kbd/scancodes-1.html
pub fn scan_code_to_key(scan_code: u32) -> Option<KeybdKey> {
  match scan_code {
    0x0e => Some(BackspaceKey),
    0x0f => Some(TabKey),
    0x1c => Some(EnterKey),
    0x01 => Some(EscapeKey),
    0x39 => Some(SpaceKey),
    0x47 => Some(HomeKey),
    0x4b => Some(LeftKey),
    0x48 => Some(UpKey),
    0x4d => Some(RightKey),
    0x50 => Some(DownKey),
    0x52 => Some(InsertKey),
    0x53 => Some(DeleteKey),
    0x0b => Some(Numrow0Key),
    0x02 => Some(Numrow1Key),
    0x03 => Some(Numrow2Key),
    0x04 => Some(Numrow3Key),
    0x05 => Some(Numrow4Key),
    0x06 => Some(Numrow5Key),
    0x07 => Some(Numrow6Key),
    0x08 => Some(Numrow7Key),
    0x09 => Some(Numrow8Key),
    0x0a => Some(Numrow9Key),
    0x1e => Some(AKey),
    0x30 => Some(BKey),
    0x2e => Some(CKey),
    0x20 => Some(DKey),
    0x12 => Some(EKey),
    0x21 => Some(FKey),
    0x22 => Some(GKey),
    0x23 => Some(HKey),
    0x17 => Some(IKey),
    0x24 => Some(JKey),
    0x25 => Some(KKey),
    0x26 => Some(LKey),
    0x32 => Some(MKey),
    0x31 => Some(NKey),
    0x18 => Some(OKey),
    0x19 => Some(PKey),
    0x10 => Some(QKey),
    0x13 => Some(RKey),
    0x1f => Some(SKey),
    0x14 => Some(TKey),
    0x16 => Some(UKey),
    0x2f => Some(VKey),
    0x11 => Some(WKey),
    0x2d => Some(XKey),
    0x15 => Some(YKey),
    0x2c => Some(ZKey),
    0x52 => Some(Numpad0Key),
    0x4f => Some(Numpad1Key),
    0x50 => Some(Numpad2Key),
    0x51 => Some(Numpad3Key),
    0x4b => Some(Numpad4Key),
    0x4c => Some(Numpad5Key),
    0x4d => Some(Numpad6Key),
    0x47 => Some(Numpad7Key),
    0x48 => Some(Numpad8Key),
    0x49 => Some(Numpad9Key),
    0x3b => Some(F1Key),
    0x3c => Some(F2Key),
    0x3d => Some(F3Key),
    0x3e => Some(F4Key),
    0x3f => Some(F5Key),
    0x40 => Some(F6Key),
    0x41 => Some(F7Key),
    0x42 => Some(F8Key),
    0x43 => Some(F9Key),
    0x44 => Some(F10Key),
    0x45 => Some(NumLockKey),
    0x46 => Some(ScrollLockKey),
    0x3a => Some(CapsLockKey),
    0x2a => Some(LShiftKey),
    0x36 => Some(RShiftKey),
    0x1d => Some(LControlKey),
    0x29 => Some(BackquoteKey),
    0x35 => Some(SlashKey),
    0x2b => Some(BackslashKey),
    0x33 => Some(CommaKey),
    0x34 => Some(PeriodKey),
    0x0c => Some(MinusKey),
    0x28 => Some(QuoteKey),
    0x27 => Some(SemicolonKey),
    0x1a => Some(LBracketKey),
    0x1b => Some(RBracketKey),
    0x0d => Some(EqualKey),
    _ => None,
  }
}

// https://www.win.tue.nl/~aeb/linux/kbd/scancodes-1.html
pub fn key_to_scan_code(key: KeybdKey) -> i32 {
  match key {
    BackspaceKey => 0x0e,
    TabKey => 0x0f,
    EnterKey => 0x1c,
    EscapeKey => 0x01,
    SpaceKey => 0x39,
    HomeKey => 0x47,
    LeftKey => 0x4b,
    UpKey => 0x48,
    RightKey => 0x4d,
    DownKey => 0x50,
    InsertKey => 0x52,
    DeleteKey => 0x53,
    Numrow0Key => 0x0b,
    Numrow1Key => 0x02,
    Numrow2Key => 0x03,
    Numrow3Key => 0x04,
    Numrow4Key => 0x05,
    Numrow5Key => 0x06,
    Numrow6Key => 0x07,
    Numrow7Key => 0x08,
    Numrow8Key => 0x09,
    Numrow9Key => 0x0a,
    AKey => 0x1e,
    BKey => 0x30,
    CKey => 0x2e,
    DKey => 0x20,
    EKey => 0x12,
    FKey => 0x21,
    GKey => 0x22,
    HKey => 0x23,
    IKey => 0x17,
    JKey => 0x24,
    KKey => 0x25,
    LKey => 0x26,
    MKey => 0x32,
    NKey => 0x31,
    OKey => 0x18,
    PKey => 0x19,
    QKey => 0x10,
    RKey => 0x13,
    SKey => 0x1f,
    TKey => 0x14,
    UKey => 0x16,
    VKey => 0x2f,
    WKey => 0x11,
    XKey => 0x2d,
    YKey => 0x15,
    ZKey => 0x2c,
    Numpad0Key => 0x52,
    Numpad1Key => 0x4f,
    Numpad2Key => 0x50,
    Numpad3Key => 0x51,
    Numpad4Key => 0x4b,
    Numpad5Key => 0x4c,
    Numpad6Key => 0x4d,
    Numpad7Key => 0x47,
    Numpad8Key => 0x48,
    Numpad9Key => 0x49,
    F1Key => 0x3b,
    F2Key => 0x3c,
    F3Key => 0x3d,
    F4Key => 0x3e,
    F5Key => 0x3f,
    F6Key => 0x40,
    F7Key => 0x41,
    F8Key => 0x42,
    F9Key => 0x43,
    F10Key => 0x44,
    NumLockKey => 0x45,
    ScrollLockKey => 0x46,
    CapsLockKey => 0x3a,
    LShiftKey => 0x2a,
    RShiftKey => 0x36,
    LControlKey => 0x1d,
    BackquoteKey => 0x29,
    SlashKey => 0x35,
    BackslashKey => 0x2b,
    CommaKey => 0x33,
    PeriodKey => 0x34,
    MinusKey => 0x0c,
    QuoteKey => 0x28,
    SemicolonKey => 0x27,
    LBracketKey => 0x1a,
    RBracketKey => 0x1b,
    EqualKey => 0x0d,
    OtherKey(code) => code as i32,
    _ => 0x0,
  }
}

impl From<MouseButton> for uinput::event::controller::Mouse {
  fn from(button: MouseButton) -> Self {
    use uinput::event::controller::Mouse;
    match button {
      MouseButton::LeftButton => Mouse::Left,
      MouseButton::RightButton => Mouse::Right,
      MouseButton::MiddleButton => Mouse::Middle,
      MouseButton::X1Button => unimplemented!(),
      MouseButton::X2Button => unimplemented!(),
      MouseButton::OtherButton(_) => unimplemented!(),
    }
  }
}
